BOOTSEG = 0x1000
.globl begtext, begdata, begbss                      ! needed by linker

! IMPORTS and EXPORTS
.globl _main,_prints,_running,_scheduler,_inkmode	 !imports
.globl _processSize,_syscallHandler,_timerHandler	 !imports
.globl _processes,_keyboardHandler					 !imports

.globl _diskr,_setes,_inces,_tswitch,_reset_video	 !exports
.globl _goUmode,_get_byte,_put_byte,_getcs,_restore	 !exports
.globl _mem_lock,_mem_unlock,_write_port,_read_port	 !exports
.globl _int80h,_thandler,_kbhandler					 !exports

.text                                                ! these tell as:	
begtext:                                             ! text,data,bss segments
.data                                                ! are all the same.
begdata:
.bss
begbss:
.text           

start:
		cli
		
        mov     ax,cs                   ! establish segments 
        mov     ds,ax                   ! we know ES,CS=0x1000. Let DS=CS  
        mov     ss,ax                   ! SS = CS ===> all point to 0x1000
        mov     es,ax
        
        mov     sp, #_processes         ! SP = 64KB
        add		sp, _processSize
        
        mov		ax, #0x0003
        int		#0x0010

        call _main                      ! call main[] in C

! if ever return, just hang
		mov		ax,#msg
		push	ax
		call	_prints
dead:	jmp dead
msg:	.asciz "BACK TO ASSEMBLY AND HANG\r\n"

!*************************************************************
!     KCW  added functions for MT system
!************************************************************
_getcs:
        mov   ax, cs
        ret

_tswitch:
		push	ax
        push	bx
        push	cx
        push	dx
        push	bp
        push	si
        push	di
        pushf
        mov		bx, _running
        mov		2[bx], sp

find:
		call	_scheduler

resume:
		mov		bx, _running
        mov		sp, 2[bx]
        popf
        pop		di
        pop		si
        pop		bp
        pop		dx
        pop		cx
        pop		bx
        pop		ax
        ret
        
MACRO INTH
		push ax
		push bx
		push cx
		push dx
		push bp
		push si
		push di
		push es
		push ds

		push cs
		pop  ds

		inc _inkmode          ! enter Kmode : ++inkmode
		cmp _inkmode,#1       ! if inkmode == 1 ==> interrupt was in Umode
		jg  ?1                ! imode>1 : was in Kmode: bypass saving uss,usp

		! was in Umode: save interrupted (SS,SP) into proc
		mov si,_running   	! ready to access proc
		mov 4[si],ss        ! save SS  in proc.USS
		mov 6[si],sp        ! save SP  in proc.USP

		! change DS,ES,SS to Kernel segment
		mov  di,ds            ! stupid !!        
		mov  es,di            ! CS=DS=SS=ES in Kmode
		mov  ss,di

		mov  sp, _running     ! sp -> running's kstack[] high end
		add  sp, _processSize

?1:		call  _?1             ! call handler in C

		br    _goUmode        ! return to interrupted point
MEND


_int80h:	INTH	syscallHandler
_thandler:	INTH	timerHandler
_kbhandler:	INTH	keyboardHandler
		
_goUmode:
		cli
		dec		_inkmode
		cmp		_inkmode, #0
		jg		xkmode
		
		! restore uSS, uSP from _running
		mov		bx,_running
		mov		cx,4[bx]
		mov		ss,cx
		mov		sp,6[bx]
		
xkmode:
		pop		ds
		pop		es
		pop		di
		pop		si
		pop		bp
		pop		dx
		pop		cx
		pop		bx
		pop		ax
		iret
		
       !---------------------------------------
       ! int diskr[cyl, head, sector, buf] 
       !            4     6     8     10
       !---------------------------------------
_diskr:
		push	bp
		mov		bp,sp
		
		movb	dl,#0x00
		movb	dh,6[bp]
		movb	cl,8[bp]
		incb	cl
		movb	ch,4[bp]
		mov		ax,#0x0202
		mov		bx,10[bp]
		int		0x13
		jb		error
		
		mov		sp,bp
		pop		bp
		ret

_setes:
		push	bp
		mov		bp,sp
		
		mov		ax,4[bp]
		mov		es,ax
		
		mov		sp,bp
		pop		bp
		ret
		
_inces:
		mov		ax,es
		add		ax,#0x40
		mov		es,ax
		ret
		
		!------------------------------
        !       error & reboot
        !------------------------------
error:
		mov		bx,#bad
		push	bx
		call	_prints
		int		0x19

bad:	.asciz	"Error!\r\n"

!*===========================================================================*
!*								 get_byte								     *
!*===========================================================================*
! This routine is used to fetch a byte from anywhere in memory.
! The call is:
!     c = get_byte[segment, offset]
! where
!     'segment' is the value to put in es
!     'offset'  is the offset from the es value
_get_byte:
		push	bp
		mov		bp,sp
		
		push	es
		push	bx
		
		mov		es,4[bp]
		mov		bx,6[bp]
		seg		es
		movb	al,[bx]
		xorb	ah,ah
		
		pop		bx
		pop		es
		
		mov		bp,sp
		pop		bp
		ret
		
!*===========================================================================*
!*								 put_byte									 *
!*===========================================================================*
! This routine is used to put a word to anywhere in memory.
! The call is:
!           put_byte[char,segment,offset]
! where
!     char is a byte
!     'segment' is a segment
!     'offset'  is the offset from the segment
_put_byte:
		push	bp
		mov		bp,sp
		
		push	es
		push	bx
		
		mov		es,6[bp]
		mov		bx,8[bp]
		mov		al,4[bp]
		seg		es
		movb	[bx],al
		
		pop		bx
		pop		es
		
		mov		bp,sp
		pop		bp
		ret

!*===========================================================================*
!*								 reset_video								 *
!*===========================================================================*
_reset_video:
		mov		ax,#0x0012
		int		0x10
		mov		ax,#0x0200
		xor		bx,bx
		xor		dx,dx
		int		0x10
		ret

!*===========================================================================*
!*								 mem_lock									 *
!*===========================================================================*
_mem_lock:
		pushf
		cli
		pop		ax
		ret

!*===========================================================================*
!*								 mem_unlock									 *
!*===========================================================================*
_mem_unlock:
		sti
		ret
		
!*===========================================================================*
!*                                restore                                    *
!*===========================================================================*
_restore:
		push	bp
		mov		bp, sp
		
		push	4[bp]
		popf
		
		mov		sp, bp
		pop		bp
		ret

!*===========================================================================*
!*								 write_port									 *
!*===========================================================================*
_write_port:
		push	bp
		mov		bp,sp
		mov		dx,4[bp]
		mov		ax,6[bp]
		outb	dx,al
		pop		bp
		ret

!*===========================================================================*
!*								 read_port									 *
!*===========================================================================*
_read_port:
		push	bp
		mov		bp,sp
		mov		dx,4[bp]
		in		ax,dx
		subb	ah,ah
		pop		bp
		ret
